package tools.chapter24;

import java.util.Random;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

/**
 * @author Kevin
 * @date 2020/4/13 22:06
 */
public class CompletableFutureDemo {

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //TeaTopDemo();
        //orRelationDemo();
        //doWithWrongCatchDemo();
        doWithWrongFinallyDemo();
    }

    public static void TeaTopDemo() {
        //任务1：洗水壶->烧开水
        CompletableFuture<Void> f1 =
                CompletableFuture.runAsync(()->{
                    System.out.println("T1:洗水壶...");
                    sleep(1, TimeUnit.SECONDS);

                    System.out.println("T1:烧开水...");
                    sleep(15, TimeUnit.SECONDS);
                });
        //任务2：洗茶壶->洗茶杯->拿茶叶
        CompletableFuture<String> f2 =
                CompletableFuture.supplyAsync(()->{
                    System.out.println("T2:洗茶壶...");
                    sleep(1, TimeUnit.SECONDS);

                    System.out.println("T2:洗茶杯...");
                    sleep(2, TimeUnit.SECONDS);

                    System.out.println("T2:拿茶叶...");
                    sleep(1, TimeUnit.SECONDS);
                    return "龙井";
                });
        //任务3：任务1和任务2完成后执行：泡茶
        CompletableFuture<String> f3 =
                f1.thenCombine(f2, (__, tf)->{
                    System.out.println("T1:拿到茶叶:" + tf);
                    System.out.println("T1:泡茶...");
                    return "上茶:" + tf;
                });
        //等待任务3执行结果
        System.out.println(f3.join());
        //System.out.println(f3.get());

        orRelationDemo();
    }

    static void sleep(int t, TimeUnit u) {
        try {
            u.sleep(t);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void orRelationDemo() {
        CompletableFuture<String> f1 =
                CompletableFuture.supplyAsync(()->{
                    int t = getRandom(5, 10);
                    sleep(t, TimeUnit.SECONDS);
                    return String.valueOf(t);
                });

        CompletableFuture<String> f2 =
                CompletableFuture.supplyAsync(()->{
                    int t = getRandom(5, 10);
                    sleep(t, TimeUnit.SECONDS);
                    return String.valueOf(t);
                });

        CompletableFuture<String> f3 =
                f1.applyToEither(f2,s -> s);

        System.out.println("隔了"+f3.join()+"秒，我使用其中一只手拿起了茶杯");
    }

    public static void doWithWrongCatchDemo() {
        CompletableFuture<Integer>
                f0 = CompletableFuture.supplyAsync(()->7/0)
                .thenApply(r->r*10)
                .exceptionally(e->0);
        System.out.println(f0.join());
    }

    public static void doWithWrongFinallyDemo() {
        CompletableFuture<Integer> f0 = CompletableFuture
                .supplyAsync(()->7/0)
                .thenApply(r->r*10)
                //.exceptionally(e->0)
                //.whenComplete((s,t)->System.out.println(s));
                .handle((s,t)->{
                    System.out.println(s);
                    if (t != null) {
                        t.printStackTrace();
                    }
                    return s;
                });
    }

    public static int getRandom(int s, int e) {
        return s + new Random().nextInt(e-s+1);
    }
}
